package com.example.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.common.base.service.impl.BaseServiceImpl;
import com.example.common.enums.ResponseCodeEnum;
import com.example.common.utils.*;
import com.example.config.webscoket.WebSocket;
import com.example.dao.PocEventDetailMapper;
import com.example.dao.PocEventMapper;
import com.example.model.entity.*;
import com.example.model.query.PocEventQuery;
import com.example.model.query.SuppliesRealinfoQuery;
import com.example.model.vo.FileVo;
import com.example.model.vo.PocEventVo;
import com.example.model.vo.SocketVo;
import com.example.service.PocEventService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

@Service
@Slf4j
public class PocEventServiceImpl extends BaseServiceImpl<PocEventMapper, PocEvent> implements PocEventService {

    //访问路径
    @Value("${real_url:}")
    private String real_url;
    //真实路径
    @Value("${real_path:}")
    private String realPath;

    @Resource
    private WebSocket webSocket;

    @Autowired
    private PocEventMapper pocEventMapper;
    @Autowired
    private PocEventDetailMapper pocEventDetailMapper;

    @Override
    public ApiResult<FileVo> imgUpload(HttpServletRequest request, HttpServletResponse response, MultipartFile file) throws Exception {
        log.info("开始上传");
        response.setContentType("text/html; charset=utf-8");
        if(!file.isEmpty()){
            //最大文件大小
//            long maxSize = 52428800;//50M
            long maxSize = 104857600;//100M
            response.setContentType("text/html; charset=UTF-8");
            //检查目录
            File uploadDir = new File(realPath);
            if(!uploadDir.isDirectory()){
                //"上传目录不存在，请确认您配置的物理路径是否正确！";
                return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_UPDATE_CHANNEL_FALSE);
            }
            //检查目录写权限
            if(!uploadDir.canWrite()){
                //"上传目录没有写权限。";
                return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_REMOVE_CHANNEL_FALSE);
            }
            //创建文件夹-正式
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            String ymd = sdf.format(new Date());
            sdf = new SimpleDateFormat("hh");
            String hh = sdf.format(new Date());
            sdf = new SimpleDateFormat("mm");
            String mm = sdf.format(new Date());

            String realpathStr = realPath +"/";
            File realFile = new File(realpathStr);
            if (!realFile.exists()) {
                realFile.mkdirs();
            }
//            realpathStr += ymd + "/"+ ymd+hh + "/"+ ymd+hh+mm+ "/";
            realpathStr += ymd +"/";
//            String realUrlStr = real_url + ymd + "/"+ ymd+hh + "/"+ ymd+hh+mm+ "/";
            String realUrlStr = real_url + ymd + "/";
            File realFile2 = new File(realpathStr);
            if (!realFile2.exists()) {
                realFile2.mkdirs();
            }
            //检查文件大小
            if(file.getSize() > maxSize){
//                msg = "上传文件太大,不能超过100M";
                return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_PAGE_CHANNEL_FALSE);
            }
            String fileName = file.getOriginalFilename();
            log.info("=========fileName========================="+fileName);
            //检查扩展名
            String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
            log.info("=========fileExt========================="+fileExt);
            SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
//            String newFile = df.format(new Date()) + "_"+ new Random().nextInt(999);
            String[] fileArr = fileName.split("\\.");
            String newFileName = "";
            if(fileArr.length > 0) {
                newFileName = fileArr[0].replaceAll("#","");
            }
            String newFile = newFileName + "_" + new Random().nextInt(9999);
            newFileName = newFile + "." + fileExt;
            log.info("=========newFileName========================="+newFile);
            File uploadedFile = new File(realpathStr, newFileName);
            //复制文件到目录下
            file.transferTo(uploadedFile);
            //访问路径
            String picUrl = realUrlStr+newFileName;
            //真实路径
            String picPath = realpathStr+newFileName;
            FileVo fileVo = new FileVo();
            fileVo.setFileSize(String.valueOf(file.getSize()));
            fileVo.setFileName(fileName);
            fileVo.setFileAddr(picUrl);
            String type = FileTypeUtil.getFileType(fileName);
            fileVo.setFileType(type);
            //视频解析生成封面图
            if(type.equals("video")){
               String posterAddr =  VideoFrameUtil.grabberVideoFramerLocal(picPath,1,newFile,realpathStr);
               fileVo.setPosterAddr(realUrlStr + posterAddr);
            }
            // AMR 转 MP3
            if(type.equals("audio")){
                String fileType =  fileName.substring(fileName.lastIndexOf(".") +1 ,fileName.length()).toUpperCase();
                String[] arr = fileName.split("\\.");
                if(fileType.equals("AMR")){
                    log.info("开始转MP3");
                    String transNewFileName = arr[0] +"trans" + ".mp3";
                    String targetPath = realpathStr + transNewFileName;
                    log.info("转MP3存储路径="+targetPath);
                    Boolean flag = FfmpegUtil.amrToMp3(picPath, targetPath);
                    if(!flag){
                        log.info("=================文件转码失败=====================");
                        return new ApiResult<>(-785,"文件转码失败");
                    }
                    fileVo.setFileName(transNewFileName);
                    fileVo.setFileAddr(realUrlStr+transNewFileName);//访问地址
                }
            }
            return new ApiResult<>(fileVo);
        }else{
            return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_SAVE_CHANNEL_NAME_FALSE);
        }
    }

    /*
    * @param path 访问路径
    * */
    @Override
    public  ApiResult<String> preview(String path) throws  Throwable{
        String realP = realPath.replaceAll("real_file/","");
        //真实存储全路径
        String newRealPath = realP + path;
        String fileName = newRealPath.substring(newRealPath.lastIndexOf("/")+1);
        String fileType = FileTOHtml.getFIleType(fileName);
        if(fileType.equals("word")){
            String newPath ;
            if(fileName.indexOf("docx")>-1){
                newPath = FileTOHtml.Word2007ToHtml(newRealPath,realPath);
            }else{
                newPath = FileTOHtml.Word2003ToHtml(newRealPath,realPath);
            }
            return new ApiResult<>(newPath);
        }else if(fileType.equals("excel")){
            StringBuilder stringBuilder = new StringBuilder();
            // 打印实现Appendable 接口，可打印到stringbuilder、stringbuffer、BufferedWriter等
            ExcelToHtml excelToHtml = ExcelToHtml.create(newRealPath, stringBuilder);
            excelToHtml.setCompleteHTML(true);// 是否打印完整html
            excelToHtml.printPage();// 打印
//            System.out.println(stringBuilder.toString());// 输出打印结果
            String result = stringBuilder.toString();
            String newFileName = String.valueOf(new Date())+".html";
            FileUtils.writeStringToFile(new File(realPath, newFileName), result, "utf-8");
            return new ApiResult<>("/materials/real_file/"+newFileName);
        }else{
            return new ApiResult<>("other");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<PocEvent> save(PocEventVo pocEventVo) throws Exception {
        if(StringUtils.isBlank(pocEventVo.getEventName())){
            return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_SELECTLIST_CHANNEL_FALSE);
        }
        if(pocEventVo.getEventType() == null){
            return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_SAVE_CUSTOMER_FALSE);
        }
        if(StringUtils.isBlank(pocEventVo.getUserTel())){
            return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_REMOVE_CUSTOMER_FALSE);
        }
        //事件附件格式校验
        List<PocEventDetail> pocEventDetailList = pocEventVo.getPocEventDetailList();
        if(pocEventDetailList.size()>0){
            for(PocEventDetail event : pocEventDetailList){
                if(StringUtils.isBlank(event.getFileType())){
                    return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_UPDATE_CUSTOMER_FALSE);
                }
            }
        }
        PocEvent pocEvent = new PocEvent();
        BeanUtils.copyProperties(pocEventVo,pocEvent);
        pocEvent.setCreateTime(new Date());
        pocEvent.setUpdateTime(new Date());
        pocEvent.setEventStatus(1L);//已提交
        this.save(pocEvent);
        if(pocEventDetailList != null && pocEventDetailList.size()>0){
            for(PocEventDetail pocEventDetail : pocEventDetailList){
                pocEventDetail.setEventId(pocEvent.getEventId());
                pocEventDetail.setCreateTime(new Date());
                pocEventDetailMapper.insert(pocEventDetail);
            }
        }
        //事件订阅上报，推送到webSocket
        if(webSocket.webSocketSet.size() >0){
            SocketVo vo = new SocketVo();
            vo.setSource("event");
            vo.setType("add");
            vo.setData(JSONUtil.parseObj(pocEvent));
            webSocket.GroupSending(JSONUtil.toJsonStr(vo),"event");
        }
        return new ApiResult<>(pocEvent);
    }

    @Override
    public ApiResult<PocEventQuery> pageUserVoByQuery(PocEventQuery query) {
        query.setOptimizeCountSql(false);
        Long current = query.getCurrent();
        query.setCurrent(1L);
        QueryWrapper<PocEvent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(PocEvent::getIsValid,1L);
        if(StringUtils.isNotBlank(query.getEventName())){
            queryWrapper.lambda().like(PocEvent::getEventName,query.getEventName());
        }
        if(query.getEventStatus()!=null && query.getEventStatus() != 0){
            queryWrapper.lambda().eq(PocEvent::getEventStatus,query.getEventStatus());
        }
        if(query.getEventType() != null ){
            queryWrapper.lambda().eq(PocEvent::getEventType,query.getEventType());
        }
        if(StringUtils.isNotBlank(query.getStartDate()) ){
            queryWrapper.lambda().ge(PocEvent::getCreateTime,query.getStartDate());
        }
        if(StringUtils.isNotBlank(query.getEndDate()) ){
            queryWrapper.lambda().le(PocEvent::getCreateTime,query.getEndDate());
        }
        if(StringUtils.isNotBlank(query.getType()) && query.getType().equals("1")){
            queryWrapper.lambda().in(PocEvent::getEventStatus,1L,2L);
        }
        if(StringUtils.isNotBlank(query.getType()) && query.getType().equals("2")){
            queryWrapper.lambda().eq(PocEvent::getEventStatus,3L);
        }
        if(StringUtils.isNotBlank(query.getUserTel())){
            queryWrapper.lambda().eq(PocEvent::getUserTel,query.getUserTel());
        }
        if(StringUtils.isNotBlank(query.getUserName())){
            queryWrapper.lambda().like(PocEvent::getUserTel,query.getUserTel()).or().like(PocEvent::getUserName,query.getUserName());
        }
        Integer total = pocEventMapper.selectCount(queryWrapper);
        query.setTotal(total);
        query.setCurrent(current);
        query.setIsValid(1L);
        pocEventMapper.pageInfoByQuery(query);
        List list = query.getRecords();
        for (int i = 0; i < list.size(); i++) {
            PocEventQuery pocEventQuery = (PocEventQuery)list.get(i);
            QueryWrapper<PocEventDetail> detailQueryWrapper = new QueryWrapper<>();
            detailQueryWrapper.lambda().eq(PocEventDetail::getEventId,pocEventQuery.getEventId())
                    .eq(PocEventDetail::getIsValid,1L);
            List<PocEventDetail> pocEventDetailList = pocEventDetailMapper.selectList(detailQueryWrapper);
            if(pocEventDetailList.size()>0){
                pocEventQuery.setPocEventDetailList(pocEventDetailList);
            }
        }
        return new ApiResult<>(query);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult<Boolean> update(PocEventVo pocEventVo) throws Exception {
        PocEvent pocEvent = new PocEvent();
        pocEventVo.setCreateTime(null);
        BeanUtils.copyProperties(pocEventVo,pocEvent);
        pocEvent.setUpdateTime(new Date());
        this.updateById(pocEvent);
        QueryWrapper<PocEventDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.lambda().eq(PocEventDetail::getEventId,pocEvent.getEventId())
                .eq(PocEventDetail::getIsValid,1L);
        List<PocEventDetail> pocEventDetailList = pocEventDetailMapper.selectList(detailQueryWrapper);
        if(pocEventDetailList.size()>0){
            for(PocEventDetail detail : pocEventDetailList){
                detail.setIsValid(0L);
                pocEventDetailMapper.updateById(detail);
            }
        }
        List<PocEventDetail> newPocEventDetailList = pocEventVo.getPocEventDetailList();
        if(newPocEventDetailList != null && newPocEventDetailList.size()>0){
            for(PocEventDetail pocEventDetail : newPocEventDetailList){
                pocEventDetail.setEventId(pocEvent.getEventId());
                pocEventDetail.setCreateTime(new Date());
                pocEventDetail.setDetailId(null);
                pocEventDetailMapper.insert(pocEventDetail);
            }
        }
        //事件状态修改，上报给调度
        if(webSocket.webSocketSet.size() > 0) {
            SocketVo vo = new SocketVo();
            vo.setSource("event");
            vo.setType("update");
            vo.setData(JSONUtil.parseObj(pocEvent));
            webSocket.GroupSending(JSONUtil.toJsonStr(vo),"event");
        }
        return new ApiResult<>(Boolean.TRUE);
    }

    @Override
    public ApiResult<PocEventVo> getInfo(String id) throws Exception{
        PocEventVo  vo = new PocEventVo();
        PocEvent pocEvent = pocEventMapper.selectById(id);
        if(pocEvent == null){
            return new ApiResult<>(ResponseCodeEnum.MALL_SERVICE_SAVE_CHANNEL_FALSE);
        }
        BeanUtils.copyProperties(pocEvent,vo);
        QueryWrapper<PocEventDetail> detailQueryWrapper = new QueryWrapper<>();
        detailQueryWrapper.lambda().eq(PocEventDetail::getEventId,pocEvent.getEventId())
                .eq(PocEventDetail::getIsValid,1L);
        List<PocEventDetail> pocEventDetailList = pocEventDetailMapper.selectList(detailQueryWrapper);
        if(pocEventDetailList.size()>0){
            vo.setPocEventDetailList(pocEventDetailList);
        }
        return new ApiResult<>(vo);
    }

    @Override
    public ApiResult<Boolean> del(String id) throws Exception{
        PocEvent pocEvent = pocEventMapper.selectById(id);
        if(pocEvent != null){
            pocEvent.setIsValid(0L);
            pocEventMapper.updateById(pocEvent);
        }
        return new ApiResult<>(Boolean.TRUE);
    }

    @Override
    public ApiResult<Boolean> modifyStatus(String id,Long status) throws Exception{
        PocEvent pocEvent = pocEventMapper.selectById(id);
        if(pocEvent != null){
            pocEvent.setEventStatus(status);
            pocEvent.setUpdateTime(new Date());
            pocEventMapper.updateById(pocEvent);
        }
        return new ApiResult<>(Boolean.TRUE);
    }

    @Override
    public ApiResult<Boolean> export(PocEventQuery query,HttpServletRequest request, HttpServletResponse response) throws Exception {
        PrintWriter out = null;
        out = response.getWriter();
        //物理路径
        String sourcePath = request.getSession().getServletContext().getRealPath("/").replaceAll("\\\\", "/");
        ExportExcelUtil exportExcel = new ExportExcelUtil();
        String excelPath = exportExcel.creatExcelFile(sourcePath, "导出上报事件信息");
        List<Map<String, String>> dataList = new ArrayList<Map<String, String>>();
        Map<String, String> titleMap = new HashMap<String, String>();
        titleMap.put("0", "事件编号");
        titleMap.put("1", "事件名称");
        titleMap.put("2", "上报人");
        titleMap.put("3", "上报时间");
        titleMap.put("4", "事件状态");
        titleMap.put("5", "事件类型");
        titleMap.put("6", "事件描述");
        titleMap.put("7", "经纬度");
        dataList.add(titleMap);
        // 获取customer集合
        QueryWrapper<PocEvent> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(PocEvent::getIsValid, 1);
        if(StringUtils.isNotBlank(query.getEventName())){
            queryWrapper.lambda().like(PocEvent::getEventName,query.getEventName());
        }
        if(query.getEventStatus()!=null && query.getEventStatus() != 0){
            queryWrapper.lambda().eq(PocEvent::getEventStatus,query.getEventStatus());
        }
        if(query.getEventType() != null ){
            queryWrapper.lambda().eq(PocEvent::getEventType,query.getEventType());
        }
        if(StringUtils.isNotBlank(query.getStartDate()) ){
            queryWrapper.lambda().ge(PocEvent::getCreateTime,query.getStartDate());
        }
        if(StringUtils.isNotBlank(query.getEndDate()) ){
            queryWrapper.lambda().le(PocEvent::getCreateTime,query.getEndDate());
        }
        if(StringUtils.isNotBlank(query.getUserTel())){
            queryWrapper.lambda().like(PocEvent::getUserTel,query.getUserTel()).or().like(PocEvent::getUserName,query.getUserName());
        }
        List<PocEvent> list = pocEventMapper.selectList(queryWrapper);
        if (list.size() > 0) {
            for (PocEvent obj : list) {
                String eventId = "";
                String eventName = "";
                String userTel = "";
                String createTime = "";
                String eventStatus = "";
                String eventType = "";
                String eventDescribe = "";
                String jwd = "";
                Map<String, String> dataMap = new HashMap<>();
                if (obj.getEventId() != null) {
                    eventId = obj.getEventId();
                }
                if (obj.getEventName() != null) {
                    eventName = obj.getEventName();
                }
                if (obj.getUserTel() != null) {
                    userTel = obj.getUserTel();
                }
                if (obj.getCreateTime() != null) {
                    createTime = DateFormatUtil.getDateTimeString(obj.getCreateTime(),"yyyy-MM-dd HH:mm");
                }
                if(obj.getEventStatus() != null){
                    if(obj.getEventStatus() == 1L){
                        eventStatus = "已提交";
                    }else if(obj.getEventStatus() == 2L){
                        eventStatus = "处理中";
                    }else if(obj.getEventStatus() == 3L){
                        eventStatus = "已完成";
                    }
                }
                if(obj.getEventType() != null){
                    if(obj.getEventType() == 1L){
                        eventType = "一般";
                    }else if(obj.getEventType() == 2L){
                        eventType = "严重";
                    }else if(obj.getEventType() == 3L){
                        eventType = "较严重";
                    }else if(obj.getEventType() == 4L){
                        eventType = "特别严重";
                    }
                }
                if(StringUtils.isNotBlank(obj.getEventDescribe())){
                    eventDescribe = obj.getEventDescribe();
                }
                 if(StringUtils.isNotBlank(obj.getEventLongitude()) && StringUtils.isNotBlank(obj.getEventLatitude())){
                     jwd = obj.getEventLongitude() +","+obj.getEventLatitude();
                 }
                dataMap.put("0", eventId);
                dataMap.put("1", eventName);
                dataMap.put("2", userTel);
                dataMap.put("3", createTime);
                dataMap.put("4", eventStatus);
                dataMap.put("5", eventType);
                dataMap.put("6", eventDescribe);
                dataMap.put("7", jwd);
                dataList.add(dataMap);
            }
        } else {
            return new ApiResult<>(ResponseCodeEnum.FDMALL_CUSTOMER_SERVICE_EXPORTECUSTOMER_FALSE);
        }
        exportExcel.importDatas(dataList);
        DownloadFileUtil.downloadLocal(excelPath, response);
        out.flush();
        out.close();
        out = null;
        return null;
    }

}
